#include "stdafx.h"
#include "Wx_GlobalData.h"
#include "Wx_AddrOffest.h"
#include "stdlib.h"
#include "include/rapidjson/writer.h"
#include "include/rapidjson/stringbuffer.h"
#include "Utils.h"
#include "Wx_Utils.h"

using namespace rapidjson;

void MsgPack(WxUserInfo* userInfo, Wx_jsonBuff* jb);
void GetInfo(WxStr* wxid, CHAR* buff);

static DWORD getFriendInfoCall1;
static DWORD getFriendInfoCall2;
static DWORD getFriendInfoCall3;

static DWORD newcall1;
static DWORD newcall2;

static DWORD agreeFriendCall1;
static DWORD agreeFriendCall2;
static DWORD agreeFriendCall3;
static DWORD agreeFriendCall4;
static DWORD agreeFriendParam;

static DWORD addFriendCall1;
static DWORD addFriendCall2;
static DWORD addFriendCall3;
static DWORD addFriendCall4;
static DWORD addFriendCall5;
static DWORD addFriendCall6;
static DWORD addFriendParam;

static DWORD deletedFriendCall1;
static DWORD deletedFriendCall2;

static DWORD deletedFriendCall3;
static DWORD deletedFriendCall4;
static DWORD deletedFriendCall5;
static DWORD deletedFriendCall6;
static DWORD deletedFriendCall7;
static DWORD deletedFriendCall8;
static DWORD deletedFriendCall9;

static DWORD deletedFriendParam1;
static DWORD deletedFriendParam2;
static DWORD deletedFriendParam3;
static DWORD deletedFriendParam4;
static DWORD deletedFriendParam5;

void Wx_GetFriendList(Wx_jsonBuff* jb) {

	PrintFunAddr((DWORD)Wx_GetFriendList);

	BinaryThreeOp binThreeOp((DWORD*)*(DWORD*)((*(DWORD*)(pFriendListHeadPointer + 0x68)) + 0x4));
	
	jb->str = std::string(binThreeOp.s.GetString());
	jb->len = binThreeOp.s.GetSize();
	//sctSocket.wxSend((CHAR*)binThreeOp.s.GetString(), binThreeOp.s.GetSize());
}

void Wx_DeleteFriend(TCHAR* deletedWxId) {

	PrintFunAddr((DWORD)Wx_DeleteFriend);

	deletedFriendCall1 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL1_OFFEST;
	deletedFriendCall2 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL2_OFFEST;

	deletedFriendCall3 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL3_OFFEST;
	deletedFriendCall4 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL4_OFFEST;
	deletedFriendCall5 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL5_OFFEST;
	deletedFriendCall6 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL6_OFFEST;
	deletedFriendCall7 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL7_OFFEST;
	deletedFriendCall8 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL8_OFFEST;
	deletedFriendCall9 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_CALL9_OFFEST;

	deletedFriendParam1 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_PARAM1_OFFEST;
	deletedFriendParam2 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_PARAM2_OFFEST;
	deletedFriendParam3 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_PARAM3_OFFEST;
	deletedFriendParam4 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_PARAM4_OFFEST;
	deletedFriendParam5 = (DWORD)hWeChatWin + ADDR_DELETEDFRIEND_PARAM5_OFFEST;

	WxStr wxDeletedWxId;
	wxDeletedWxId.str = deletedWxId;
	wxDeletedWxId.countLen();

	WxStr wxTempBuff;

	__asm {
		call[deletedFriendCall1]
		mov al, 0x1
		lea edi, wxDeletedWxId
		mov ecx, edi
		call[deletedFriendCall2]

		push 0x0
		push 0x0
		push 0x0
		push 0xFF
		push 0x0
		push 0x0
		push 0x0
		push 0xFF
		push 0x0
		push 0x0
		push 0x0
		push 0xFF
		push 0x0
		push 0x0
		push 0x0
		push 0xFF
		push 0x0
		push 0x0
		push 0x0
		push 0xFF
		push 0x0
		push 0x0
		push 0x0
		push 0x0
		push 0x0
		mov ecx, esp
		push edi
		lea eax, [esp + 0x18]
		call [deletedFriendCall3]
		lea ecx, wxTempBuff
		call [deletedFriendCall4]
		add esp, 0x14
		mov ecx, eax
		call [deletedFriendCall5]
		sub esp, 0x10
		mov edx, [deletedFriendParam2]
		mov ecx, esp
		push [deletedFriendParam3]
		push [deletedFriendParam4]
		mov byte ptr ds : [ecx] , 0x2
		mov dword ptr ds : [ecx + 0x8] , eax
		mov ecx, 0x2
		push [deletedFriendParam5]
		push 0xEE
		call [deletedFriendCall6]
		add esp, 0x70
		lea ecx, wxTempBuff
		call [deletedFriendCall7]
		call [deletedFriendCall8]
		push ecx
		push edi
		call [deletedFriendCall9]


	}

}

void Wx_AddFriend(TCHAR* addedWxid, TCHAR* text, DWORD addWay = 0x6) {

	PrintFunAddr((DWORD)Wx_AddFriend);

	addFriendCall1 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL1_OFFEST;
	addFriendCall2 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL2_OFFEST;
	addFriendCall3 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL3_OFFEST;
	addFriendCall4 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL4_OFFEST;
	addFriendCall5 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL5_OFFEST;
	addFriendCall6 = (DWORD)hWeChatWin + ADDR_ADDFRIEND_CALL6_OFFEST;
	addFriendParam = (DWORD)hWeChatWin + ADDR_ADDFRIEND_PARAM_OFFEST;

	WxStr wxAddedWxId;
	wxAddedWxId.str = addedWxid;
	wxAddedWxId.countLen();

	CHAR tempBuff[0x3C] = { 0 };

	__asm{


		sub esp, 0x18
		mov ecx, esp
		mov dword ptr ss : [ebp - 0xDC] , esp
		push [addFriendParam]
		call [addFriendCall5]
		sub esp, 0x18
		lea eax, tempBuff
		mov dword ptr ss : [ebp - 0xE4] , esp
		mov ecx, esp
		push eax
		call [addFriendCall6]

		push addWay
		sub esp, 0x14
		mov ecx, esp
		mov dword ptr ss : [ebp - 0xE8] , esp
		push -0x1
		mov edi, text
		push edi
		call [addFriendCall1]
		push 0x2
		sub esp, 0x14
		mov ecx, esp
		mov dword ptr ss : [ebp - 0xE0] , esp
		lea ebx, wxAddedWxId
		push ebx
		call [addFriendCall2]
		call [addFriendCall3]
		mov ecx, eax
		call [addFriendCall4]
	}

}

void Wx_AgreeFriend(TCHAR* v1, TCHAR* v2) {

	PrintFunAddr((DWORD)Wx_AgreeFriend);

	agreeFriendCall1 = (DWORD)hWeChatWin + ADDR_AGREEFRIEND_CALL1_OFFEST;
	agreeFriendCall2 = (DWORD)hWeChatWin + ADDR_AGREEFRIEND_CALL2_OFFEST;
	agreeFriendCall3 = (DWORD)hWeChatWin + ADDR_AGREEFRIEND_CALL3_OFFEST;
	agreeFriendCall4 = (DWORD)hWeChatWin + ADDR_AGREEFRIEND_CALL4_OFFEST;
	agreeFriendParam = (DWORD)hWeChatWin + ADDR_AGREEFRIEND_PARAM_OFFEST;

	CHAR v2Buff[0x2a0] = { 0 };
	*(DWORD*)(v2Buff + 0x24c) = 0x25;
	*(DWORD*)(v2Buff + 0x290) = (DWORD)v2;
	*(DWORD*)(v2Buff + 0x294) = wcslen(v2);
	*(DWORD*)(v2Buff + 0x298) = wcslen(v2) * 2;

	CHAR v1Buff[0x430] = { 0 };
	*(DWORD*)(v1Buff + 0x42c) = (DWORD)&v2Buff;
	*(DWORD*)(v1Buff + 0x4) = (DWORD)v1;
	*(DWORD*)(v1Buff + 0x8) = wcslen(v1);
	*(DWORD*)(v1Buff + 0xc) = wcslen(v1) * 2;

	CHAR wxV1Buff[0x3C] = { 0 };

	DWORD temp = 0;

	__asm {

		lea ecx, v1Buff
		push 0xe
		sub esp, 0x14
		push esp
		call[agreeFriendCall1]
		lea ecx, v1Buff
		lea eax, wxV1Buff
		push eax
		call[agreeFriendCall2]
		mov esi, eax
		sub esp, 0x8
		mov ecx, [agreeFriendParam]
		mov ecx, [ecx]
		call[agreeFriendCall3]
		push eax
		lea ecx, temp
		push ecx
		lea esi, wxV1Buff
		push esi
		call[agreeFriendCall4]

	}

}

void Wx_GetInfoByWxid(TCHAR* wxid, CHAR* friendInfoBuff) {

	void(*pWx_GetInfoByWxid)(TCHAR*, CHAR*);
	pWx_GetInfoByWxid = Wx_GetInfoByWxid;
	PrintFunAddr((DWORD)pWx_GetInfoByWxid);

	WxStr wxStr;
	wxStr.str = wxid;
	wxStr.len = wcslen(wxid);
	wxStr.maxLen = wcslen(wxid) * 2;

	GetInfo(&wxStr, friendInfoBuff);

}


WxUserInfo Wx_GetInfoByWxid(TCHAR* wxid, Wx_jsonBuff* jb, bool isSend = true) {


	WxUserInfo(*pWx_GetInfoByWxid)(TCHAR*, Wx_jsonBuff*, bool);
	pWx_GetInfoByWxid = Wx_GetInfoByWxid;
	PrintFunAddr((DWORD)pWx_GetInfoByWxid);

	CHAR friendInfoBuff[0x3E0] = { 0 };

	WxStr wxStr;
	wxStr.str = wxid;
	wxStr.len = wcslen(wxid);
	wxStr.maxLen = wcslen(wxid) * 2;

	GetInfo(&wxStr, friendInfoBuff);

	WxUserInfo userInfo;

	userInfo.wxid = (TCHAR*) * ((DWORD*)(friendInfoBuff + 0x8));

	if (*((DWORD*)(friendInfoBuff + 0x1c)) > 0) {
		userInfo.wxNumber = (TCHAR*) * ((DWORD*)(friendInfoBuff + 0x1c));
	}
	userInfo.wxNumberLen =  * ((DWORD*)(friendInfoBuff + 0x20));

	if (*((DWORD*)(friendInfoBuff + 0x30)) > 0) {
		userInfo.v1 = (TCHAR*) * ((DWORD*)(friendInfoBuff + 0x30));
	}
	userInfo.v1Len = *((DWORD*)(friendInfoBuff + 0x34));

	if (*((DWORD*)(friendInfoBuff + 0x50)) > 0) {
		userInfo.remark = (TCHAR*) * ((DWORD*)(friendInfoBuff + 0x50));
	}
	userInfo.remarkLen = *((DWORD*)(friendInfoBuff + 0x54));

	userInfo.nickName = (TCHAR*) * ((DWORD*)(friendInfoBuff + 0x64));

	if (isSend) {
		MsgPack(&userInfo, jb);
	}
	
	return userInfo;

}

void MsgPack(WxUserInfo* userInfo, Wx_jsonBuff* jb) {

	StringBuffer s;
	Writer<StringBuffer, UTF16<>> writer(s);

	writer.StartObject();

	writer.Key(L"type");
	writer.String(L"Wx_GetInfoByWxid");

	writer.Key(L"status");
	writer.String(L"success");

	writer.Key(L"wxid");
	writer.String(wxOwnInfo.wxId);

	writer.Key(L"content");

	writer.StartObject();

	writer.Key(L"wxid");
	writer.String(userInfo->wxid);

	writer.Key(L"wxNumber");
	writer.String(userInfo->wxNumber, userInfo->wxNumberLen);

	writer.Key(L"v1");
	writer.String(userInfo->v1, userInfo->v1Len);

	writer.Key(L"remark");
	writer.String(userInfo->remark, userInfo->remarkLen);

	writer.Key(L"nickName");
	writer.String(userInfo->nickName);

	/*
	writer.Key(L"nickNameByFirstLetterUpper");
	writer.String((TCHAR*)* ((DWORD*)(str + 0xa4)));

	writer.Key(L"nickNameBySpell");
	writer.String((TCHAR*)*((DWORD*)(str + 0xb8)));

	
	writer.Key(L"smallHeadImage");
	writer.String((TCHAR*)*((DWORD*)(str + 0xf4)));

	writer.Key(L"bigHeadImage");
	writer.String((TCHAR*)*((DWORD*)(str + 0x108)));

	writer.Key(L"unknownData");
	writer.String((TCHAR*)*((DWORD*)(str + 0x11c)));

	writer.Key(L"signature");
	writer.String((TCHAR*)*((DWORD*)(str + 0x194)));

	writer.Key(L"country");
	writer.String((TCHAR*)*((DWORD*)(str + 0x1a8)));

	writer.Key(L"provice");
	writer.String((TCHAR*)*((DWORD*)(str + 0x1bc)));

	writer.Key(L"city");
	writer.String((TCHAR*)*((DWORD*)(str + 0x1d0)));

	writer.Key(L"friendSource");
	DWORD num = (DWORD)* (DWORD*)(str + 0x1e4);
	TCHAR ss[10] = {0};
	_itow_s(num, ss, 16);
	writer.String(ss);

	writer.Key(L"friendCircleBgImage");
	writer.String((TCHAR*)* ((DWORD*)(str + 0x274)));
	*/

	writer.EndObject();

	writer.EndObject();

	jb->str = std::string(s.GetString());
	jb->len = s.GetSize();
	//sctSocket.wxSend((CHAR*)s.GetString(), s.GetSize());
}

void GetInfo(WxStr* wxid, CHAR* buff) {

	/*
	newcall1 = (DWORD)hWeChatWin + 0x4A4810;
	newcall2 = (DWORD)hWeChatWin + 0x27F4F0;
	WxStr wxidBuff;
	*/

	getFriendInfoCall1 = (DWORD)hWeChatWin + ADDR_GETFRIENDINFO_CALL1_OFFEST;
	getFriendInfoCall2 = (DWORD)hWeChatWin + ADDR_GETFRIENDINFO_CALL2_OFFEST;
	getFriendInfoCall3 = (DWORD)hWeChatWin + ADDR_GETFRIENDINFO_CALL3_OFFEST;

	/*
	__asm {

		lea eax, friendInfoBuff
		push eax
		sub esp, 0x14
		mov ecx, esp
		mov dword ptr ss : [ebp - 0x10] , esp
		push - 0x1
		lea ecx, wxidBuff
		push[wxStr]
		call[newcall1]
		call[newcall2]

	}
	*/
	
	__asm {
		mov edi, buff
		push edi
		sub esp, 0x14
		mov eax, wxid
		mov ecx, esp
		mov dword ptr ss : [ebp - 0x2C] , esp
		push eax
		call[getFriendInfoCall1]
		call[getFriendInfoCall2]
		call[getFriendInfoCall3]
	}


}